package com.example.backend.common.aspect;

import com.example.backend.common.annotation.OperationLog;
import com.example.backend.common.utils.IpUtils;
import com.example.backend.common.utils.RequestUtils;
import com.example.backend.service.OperationLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class OperationLogAspect {
    
    private final OperationLogService operationLogService;
    private final ObjectMapper objectMapper;
    
    @Around("@annotation(com.example.backend.common.annotation.OperationLog)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        com.example.backend.entity.OperationLog operLog = new com.example.backend.entity.OperationLog();
        
        // 设置操作时间
        operLog.setCreateTime(LocalDateTime.now());
        
        // 获取当前用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            operLog.setUsername(authentication.getName());
        }
        
        // 设置请求信息
        operLog.setIp(IpUtils.getIpAddr());
        operLog.setUrl(RequestUtils.getRequestUrl());
        operLog.setMethod(RequestUtils.getMethod());
        
        // 设置请求参数
        try {
            String params = objectMapper.writeValueAsString(point.getArgs());
            operLog.setParams(params);
        } catch (Exception e) {
            log.error("记录操作日志异常：", e);
        }
        
        // 获取注解信息
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        OperationLog annotation = method.getAnnotation(OperationLog.class);
        operLog.setModule(annotation.module());
        operLog.setType(annotation.type());
        operLog.setDescription(annotation.description());
        
        try {
            // 执行原方法
            Object result = point.proceed();
            operLog.setStatus(1);
            return result;
        } catch (Exception e) {
            operLog.setStatus(0);
            operLog.setErrorMsg(e.getMessage());
            throw e;
        } finally {
            // 保存日志
            operationLogService.save(operLog);
        }
    }
} 